/*
	FileName : bsp_flash.c
	Description : 
	
	Created on 2014.12.16 by ZZP.
	
	Revision History:
	
*/

#include "STM32F2xx_hal.h"
#include "bsp_flash.h"

#define DEBUG_DISABLE_FLASH_PROTECT		0



/* Private function prototypes -----------------------------------------------*/
static uint32_t GetSector(uint32_t Address);



///////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////
uint8_t BSP_Flash_EraseSectors(uint32_t start_sec, uint32_t end_sec)
{
	static FLASH_EraseInitTypeDef EraseInitStruct;
	uint32_t FirstSector = 0, NbOfSectors = 0, SectorError;
	uint8_t err = 0;
	
	HAL_FLASH_Unlock();
	
	/* Get the 1st sector to erase */
	FirstSector = GetSector(start_sec);
	/* Get the number of sector to erase from 1st sector*/
	NbOfSectors = GetSector(end_sec) - FirstSector + 1;

	/* Fill EraseInit structure*/
	EraseInitStruct.TypeErase = TYPEERASE_SECTORS;
	EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3;
	EraseInitStruct.Sector = FirstSector;
	EraseInitStruct.NbSectors = NbOfSectors;

	if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK)
		err = 1;
	
	HAL_FLASH_Lock();
	
	return err;
}

uint8_t BSP_Flash_Program(uint32_t addr, uint8_t *data, uint16_t len)
{
	uint8_t err = 0;
	uint32_t i, address = addr, *p32;
	
	HAL_FLASH_Unlock();
	
	p32 = (uint32_t *)data;
	for (i = 0; i < len / 4; i++){
		
		if (HAL_FLASH_Program(TYPEPROGRAM_WORD, address, *p32) == HAL_OK){
			
			address = address + 4;
			p32++;
		}
		else{
			
			err = 1;
			break;
		}
    }
	
	HAL_FLASH_Lock();
	
	return err;
}

uint8_t BSP_Flash_Read(uint32_t addr, uint8_t *data, uint16_t len)
{
	uint32_t i, Address, *p32;
	
	Address = addr;
	p32 = (uint32_t *)data;

	for (i = 0; i < len / 4; i++){
		
		*p32++ = *(__IO uint32_t *)Address;
		
		Address += 4;
	}
	return 0;
}


uint8_t BSP_Flash_WriteProtection(uint32_t WRPSec, uint8_t Enable)
{
	FLASH_OBProgramInitTypeDef OBInit;
	__IO uint32_t SectorsWRPStatus = 0xFFF;
	uint8_t err = 0;
	
	/* Get FLASH_WRP_SECTORS write protection status */
	HAL_FLASHEx_OBGetConfig(&OBInit);
	SectorsWRPStatus = OBInit.WRPSector & WRPSec;

    if (SectorsWRPStatus == 0)
    {
		/* If FLASH_WRP_SECTORS are write protected, disable the write protection */

		if (Enable)
			return 0;
		
		/* Allow Access to option bytes sector */
		HAL_FLASH_OB_Unlock();

		/* Allow Access to Flash control registers and user Falsh */
		HAL_FLASH_Unlock();

		/* Disable FLASH_WRP_SECTORS write protection */
		OBInit.OptionType = OPTIONBYTE_WRP;
		OBInit.WRPState   = WRPSTATE_DISABLE;
		OBInit.WRPSector  = WRPSec;
		HAL_FLASHEx_OBProgram(&OBInit);

		/* Start the Option Bytes programming process */
		if (HAL_FLASH_OB_Launch() != HAL_OK)
		{
			/* User can add here some code to deal with this error */
			err = 1;
		}

		/* Prevent Access to option bytes sector */
		HAL_FLASH_OB_Lock();

		/* Disable the Flash option control register access (recommended to protect
		the option Bytes against possible unwanted operations) */
		HAL_FLASH_Lock();
	}
	else{
		
		/* If FLASH_WRP_SECTORS are not write protected, enable the write protection */

		if (!Enable)
			return 0;
		
#if (DEBUG_DISABLE_FLASH_PROTECT==0)
		/* Allow Access to option bytes sector */
		HAL_FLASH_OB_Unlock();

		/* Allow Access to Flash control registers and user Falsh */
		HAL_FLASH_Unlock();

		/* Enable FLASH_WRP_SECTORS write protection */
		OBInit.OptionType = OPTIONBYTE_WRP;
		OBInit.WRPState   = WRPSTATE_ENABLE;
		OBInit.WRPSector  = WRPSec;
		HAL_FLASHEx_OBProgram(&OBInit);

		/* Start the Option Bytes programming process */
		if (HAL_FLASH_OB_Launch() != HAL_OK)
		{
			/* User can add here some code to deal with this error */
			err = 1;
		}

		/* Prevent Access to option bytes sector */
		HAL_FLASH_OB_Lock();

		/* Disable the Flash option control register access (recommended to protect
		the option Bytes against possible unwanted operations) */
		HAL_FLASH_Lock();
#endif
	}
	
	return err;
}



static uint32_t GetSector(uint32_t Address)
{
  uint32_t sector = 0;

  if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
  {
    sector = FLASH_SECTOR_0;
  }
  else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
  {
    sector = FLASH_SECTOR_1;
  }
  else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
  {
    sector = FLASH_SECTOR_2;
  }
  else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
  {
    sector = FLASH_SECTOR_3;
  }
  else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
  {
    sector = FLASH_SECTOR_4;
  }
  else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
  {
    sector = FLASH_SECTOR_5;
  }
  else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
  {
    sector = FLASH_SECTOR_6;
  }
  else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7))
  {
    sector = FLASH_SECTOR_7;
  }
  else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8))
  {
    sector = FLASH_SECTOR_8;
  }
  else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9))
  {
    sector = FLASH_SECTOR_9;
  }
  else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10))
  {
    sector = FLASH_SECTOR_10;
  }
  else /* (Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_11) */
  {
    sector = FLASH_SECTOR_11;
  }

  return sector;
}



